<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>无纺布袋重量计算器</title>
  <style>
    body {
      font-family: "Microsoft YaHei", sans-serif;
      background-color: #f5f7fa;
      color: #333;
      margin: 0;
      padding: 20px;
    }
    .container {
      max-width: 1000px;
      margin: auto;
      background: white;
      border-radius: 10px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      padding: 20px;
    }
    h1 {
      text-align: center;
      color: #2c3e50;
    }
    .section {
      display: flex;
      gap: 20px;
      margin-bottom: 20px;
    }
    .half {
      flex: 1;
      padding: 15px;
      border: 1px solid #ddd;
      border-radius: 8px;
      background: #f9f9f9;
    }
    .form-group {
      margin-bottom: 12px;
    }
    label {
      display: block;
      margin-bottom: 5px;
      font-weight: bold;
    }
    input[type="number"] {
      width: 100%;
      padding: 8px;
      border: 1px solid #ccc;
      border-radius: 4px;
      box-sizing: border-box;
    }
    .result {
      margin-top: 20px;
      padding: 10px;
      background: #e8f5e8;
      border: 1px solid #a5d6a7;
      border-radius: 8px;
      font-size: 14px;
      line-height: 1.4;
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
      gap: 6px 12px;
    }
    .result h3 {
      grid-column: 1 / -1;
      margin: 0 0 8px;
      font-size: 16px;
    }
    .result p {
      margin: 0;
    }
    #W_b_formula, #W_s_formula, #W_tot_formula {
      font-family: Menlo, Consolas, Monaco, "Courier New", monospace;
      font-size: 13px;
      overflow-wrap: anywhere;
    }
    .error {
      color: red;
      font-size: 14px;
      margin-top: 5px;
    }
    button {
      background-color: #3498db;
      color: white;
      border: none;
      padding: 10px 15px;
      border-radius: 4px;
      cursor: pointer;
      margin-top: 10px;
    }
    button:hover {
      background-color: #2980b9;
    }
    .footer {
      text-align: center;
      margin-top: 20px;
      font-size: 12px;
      color: #777;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>无纺布袋重量计算器</h1>

    

    <div class="section">
      <!-- 袋身部分 -->
      <div class="half">
        <h2>袋身</h2>
        <div class="form-group">
          <label for="H">高度 H (cm):</label>
          <input type="number" id="H" step="0.1" min="1" required />
        </div>
        <div class="form-group">
          <label for="W">宽度 W (cm):</label>
          <input type="number" id="W" step="0.1" min="1" required />
        </div>
        <div class="form-group">
          <label for="base_b">基准克重（固定）:</label>
          <input type="number" id="base_b" value="0.028" step="0.001" disabled />
        </div>
        <div class="form-group">
          <label for="t">厚度系数<small>(请输入 5-20)</small>:</label>
          <input type="number" id="t" value="12" step="1" min="5" max="20" placeholder="5-20" required />
        </div>
        <div class="form-group">
          <label>
            <input type="checkbox" id="bottomEnabled" /> 是否有底部
          </label>
        </div>
        <div class="form-group" id="bottomWidthGroup" style="display:none">
          <label for="B">底部宽度 B (cm):</label>
          <input type="number" id="B" step="0.1" min="0.1" placeholder="请输入底部宽度" />
        </div>
        <div class="form-group">
          <label>
            <input type="checkbox" id="sideEnabled" disabled /> 是否有侧边（需先开启底部）
          </label>
        </div>
        <div class="form-group" id="sideDimsGroup" style="display:none">
          <label>侧边尺寸（自动计算，cm）</label>
          <div class="form-group">
            <label for="side_len_cm">侧边长度（cm）:</label>
            <input type="number" id="side_len_cm" disabled />
          </div>
          <div class="form-group">
            <label for="side_w_cm">侧边宽度（cm）:</label>
            <input type="number" id="side_w_cm" disabled />
          </div>
        </div>
      </div>

      <!-- 手提绳部分 -->
      <div class="half">
        <h2>手提绳</h2>
        <div class="form-group">
          <label for="L">长度 L (cm):</label>
          <input type="number" id="L" value="130" step="0.1" min="1" required />
        </div>
        <div class="form-group">
          <label for="S">宽度 S (cm):</label>
          <input type="number" id="S" value="6.1" step="0.1" min="0.1" required />
        </div>
        <div class="form-group">
          <label for="base_s">基准克重（固定）:</label>
          <input type="number" id="base_s" value="0.028" step="0.001" disabled />
        </div>
        <div class="form-group">
          <label for="t_s">厚度系数<small>(请输入 5-20)</small>:</label>
          <input type="number" id="t_s" value="10" step="1" min="5" max="20" placeholder="5-20" required />
        </div>
      </div>
    </div>

    <!-- 结果输出 -->
    <div class="result" id="result" style="display:none">
      <h3>计算结果：</h3>
      <p id="bag_dims"><strong>袋身面积:</strong> <span id="bag_dims_text">H'=0.90m, W'=0.38m, A=0.342㎡</span></p>
      <p><strong>袋身重量:</strong> <span id="W_b_formula">0.90×0.38×0.028×10 = 0.09576</span> kg</p>
      <p><strong>手提绳面积:</strong> <span id="A_s_tot">0.0793</span> ㎡</p>
      <p><strong>手提绳重量:</strong> <span id="W_s_formula">1.30×0.061×0.028×10 = 0.022204</span> kg</p>
      <p id="side_section" style="display:none"><strong>侧边重量:</strong> <span id="W_side_formula"></span> kg</p>
      <p><strong>总重量:</strong> <span id="W_tot_formula">0.09576 + 0.022204 =</span> <strong id="W_tot_value">0.117964千克</strong></p>
    </div>

    <!-- 计算按钮 -->
    <button onclick="calculate()">重新计算</button>

    <div class="footer">
      <p>© 2025 无纺布袋重量计算器 | 基于规则：重量 = 面积 × (280 × 厚度系数)</p>
    </div>
  </div>

  <script>
    // 获取所有输入框
    const inputs = {
      base_b: document.getElementById("base_b"),
      base_s: document.getElementById("base_s"),
      H: document.getElementById("H"),
      W: document.getElementById("W"),
      t: document.getElementById("t"),
      bottomEnabled: document.getElementById("bottomEnabled"),
      sideEnabled: document.getElementById("sideEnabled"),
      B: document.getElementById("B"),
      L: document.getElementById("L"),
      S: document.getElementById("S"),
      t_s: document.getElementById("t_s")
    };
    const bottomWidthGroup = document.getElementById("bottomWidthGroup");
    const sideDimsGroup = document.getElementById("sideDimsGroup");
    const sideLenCm = document.getElementById("side_len_cm");
    const sideWCm = document.getElementById("side_w_cm");

    // 获取输出元素
    const outputs = {
      A_s_tot: document.getElementById("A_s_tot"),
      W_b_formula: document.getElementById("W_b_formula"),
      W_s_formula: document.getElementById("W_s_formula"),
      W_tot_formula: document.getElementById("W_tot_formula")
    };
    const bagDimsTextEl = document.getElementById("bag_dims_text");
    const resultEl = document.getElementById("result");

    // 初始计算（不弹出错误）
    calculate(true);

    // iOS/Android 兼容：给数字输入强制 decimal 键盘
    document.querySelectorAll('input[type="number"]').forEach(el => {
      el.setAttribute('inputmode', 'decimal');
      el.setAttribute('pattern', '[0-9]*');
      el.setAttribute('enterkeyhint', 'done');
    });

    // 实时监听输入变化（input 时静默计算；change/blur/Enter 时显示校验）
    Object.keys(inputs).forEach(key => {
      inputs[key].addEventListener("input", () => calculate(true));
      inputs[key].addEventListener("change", () => calculate(false));
      inputs[key].addEventListener("blur", () => calculate(false));
      inputs[key].addEventListener("keyup", (e) => {
        if (e.key === "Enter") {
          calculate(false);
          if (document.activeElement && document.activeElement.blur) document.activeElement.blur();
        }
      });
    });
    // 监听开关显示/禁用逻辑
    inputs.bottomEnabled.addEventListener("change", () => {
      const enabled = inputs.bottomEnabled.checked;
      bottomWidthGroup.style.display = enabled ? "block" : "none";
      inputs.sideEnabled.disabled = !enabled;
      if (!enabled) {
        inputs.sideEnabled.checked = false;
        inputs.B.value = "";
      }
      calculate(true);
    });
    inputs.sideEnabled.addEventListener("change", () => {
      sideDimsGroup.style.display = inputs.sideEnabled.checked ? "block" : "none";
      calculate(true);
    });

    function calculate(suppressErrors = false) {
      // 默认隐藏结果，待验证通过后再显示
      resultEl.style.display = "none";
      // 获取输入值并验证
      const base_b = Number(inputs.base_b.value);
      const base_s = Number(inputs.base_s.value);
      const H = Number(inputs.H.value);
      const W = Number(inputs.W.value);
      const t = Number(inputs.t.value);
      const bottomEnabled = inputs.bottomEnabled.checked;
      const sideEnabled = inputs.sideEnabled.checked;
      const B = Number(inputs.B.value);
      const L = Number(inputs.L.value);
      const S = Number(inputs.S.value);
      const t_s = Number(inputs.t_s.value);

      // 验证输入是否合法
      if (!isFinite(H) || H <= 0) {
        showError("H", "请输入有效的正数", suppressErrors);
        return;
      }
      if (!isFinite(W) || W <= 0) {
        showError("W", "请输入有效的正数", suppressErrors);
        return;
      }
      if (!isFinite(t) || t < 5 || t > 20) {
        showError("t", "请输入 5-20 的整数", suppressErrors);
        return;
      }
      if (bottomEnabled) {
        if (!isFinite(B) || B <= 0) {
          showError("B", "请在开启底部后输入有效的底部宽度B", suppressErrors);
          return;
        }
      }
      if (!isFinite(L) || L <= 0) {
        showError("L", "请输入有效的正数", suppressErrors);
        return;
      }
      if (!isFinite(S) || S <= 0) {
        showError("S", "请输入有效的正数", suppressErrors);
        return;
      }
      if (!isFinite(t_s) || t_s < 5 || t_s > 20) {
        showError("t_s", "请输入 5-20 的整数", suppressErrors);
        return;
      }

      // 清除错误提示
      clearErrors();

      // 计算袋身
      const H_prime_cm = 2 * H + 10;
      const W_prime_cm = W + 3;
      const H_prime = H_prime_cm / 100; // m
      const W_prime = W_prime_cm / 100; // m
      const b_m = bottomEnabled ? (B || 0) / 100 : 0; // m
      const H_effective = H_prime + b_m; // 合并高度（含底部）
      // 袋身面积（不包含侧边），用合并后的高度计算
      let A_b = H_effective * W_prime; // m²
      // 侧边（依赖底部）单独计算
      let A_side = 0;
      let W_side = 0;
      if (bottomEnabled && sideEnabled) {
        const H2_cm = H + 5;
        const h_side = H2_cm / 100; // m
        const b_side = ((B || 0) + 2) / 100; // m
        const A_side_one = h_side * b_side;
        A_side = 2 * A_side_one;
        // 显示侧边长宽（cm）
        if (typeof sideLenCm !== 'undefined' && sideLenCm) sideLenCm.value = H2_cm.toFixed(1);
        if (typeof sideWCm !== 'undefined' && sideWCm) sideWCm.value = ((B || 0) + 2).toFixed(1);
        // 侧边重量使用袋身参数 base_b 与 t
        W_side = A_side * base_b * t;
      } else {
        // 清空侧边显示
        if (typeof sideLenCm !== 'undefined' && sideLenCm) sideLenCm.value = "";
        if (typeof sideWCm !== 'undefined' && sideWCm) sideWCm.value = "";
      }
      const G = base_b; // 展示为袋身基准克重 0.028
      const W_b = A_b * base_b * t; // kg

      // 计算手提绳
      const L_m = L / 100; // m（由 cm 转换）
      const S_m = S / 100; // m（由 cm 转换）
      const A_s_tot = L_m * S_m; // m²，按输入计算
      const G_s = base_s; // 展示为手提绳基准克重 0.028
      const W_s = A_s_tot * base_s * t_s; // kg

      // 总重量
      const W_tot = W_b + W_side + W_s;

      // 更新输出
      resultEl.style.display = "block";
      outputs.A_s_tot.textContent = A_s_tot.toFixed(4);
      // 袋身面积与尺寸说明（合并底部到高度）
      const bagDimsText = bottomEnabled
        ? `H'=${H_prime.toFixed(2)}m +(底部${b_m.toFixed(2)}m) = ${H_effective.toFixed(2)}m, W'=${W_prime.toFixed(2)}m, A=${A_b.toFixed(3)}㎡`
        : `H'=${H_prime.toFixed(2)}m, W'=${W_prime.toFixed(2)}m, A=${A_b.toFixed(3)}㎡`;
      bagDimsTextEl.textContent = bagDimsText;
      // 袋身重量按 A × base × t
      outputs.W_b_formula.textContent = `${A_b.toFixed(3)} × ${base_b.toFixed(3)} × ${t.toFixed(0)} = ${W_b.toFixed(6)}`;
      outputs.W_s_formula.textContent = `${L_m.toFixed(2)} × ${S_m.toFixed(3)} × ${base_s.toFixed(3)} × ${t_s.toFixed(0)} = ${W_s.toFixed(6)}`;
      // 侧边展示
      const sideSection = document.getElementById("side_section");
      const W_side_formula = document.getElementById("W_side_formula");
      if (bottomEnabled && sideEnabled) {
        const h_side = (H + 5) / 100;
        const b_side = ((B || 0) + 2) / 100;
        W_side_formula.textContent = `2 × (${h_side.toFixed(2)}×${b_side.toFixed(2)}) × ${base_b.toFixed(3)} × ${t.toFixed(0)} = ${W_side.toFixed(6)}`;
        sideSection.style.display = "block";
      } else {
        W_side_formula.textContent = "";
        sideSection.style.display = "none";
      }
      // 总重量组成（带标注）
      if (bottomEnabled && sideEnabled) {
        outputs.W_tot_formula.textContent = `${W_b.toFixed(6)}（袋身） + ${W_side.toFixed(6)}（侧边） + ${W_s.toFixed(6)}（手提绳） =`;
      } else {
        outputs.W_tot_formula.textContent = `${W_b.toFixed(6)}（袋身） + ${W_s.toFixed(6)}（手提绳） =`;
      }
      const totValueEl = document.getElementById("W_tot_value");
      if (totValueEl) {
        totValueEl.textContent = `${W_tot.toFixed(6)}千克`;
      }
    }

    function showError(field, message, suppress = false) {
      const el = inputs[field];
      el.style.borderColor = "red";
      if (suppress) return;
      if (!el.nextElementSibling || !el.nextElementSibling.classList.contains("error")) {
        const errorDiv = document.createElement("div");
        errorDiv.className = "error";
        errorDiv.textContent = message;
        el.parentNode.appendChild(errorDiv);
      }
    }

    function clearErrors() {
      Object.keys(inputs).forEach(key => {
        inputs[key].style.borderColor = "#ccc";
        const error = inputs[key].nextElementSibling;
        if (error && error.classList.contains("error")) {
          error.remove();
        }
      });
    }
    // Android 软键盘收起：点击空白处或滚动时尝试 blur
    document.addEventListener('touchend', (e) => {
      const active = document.activeElement;
      if (active && active.tagName === 'INPUT' && !active.contains(e.target)) {
        active.blur();
      }
    });
  </script>
</body>
</html>